using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System.Collections.Generic;
using Xunit;
using Xunit.Abstractions;
namespace Odyssey.Consul.xUnit
{
    using Features.Rules;
    using Http;
    using Models;
    using Models.Internal;

    public class xUnitACLs
    {

        ITestOutputHelper outputHelper;

        public xUnitACLs(ITestOutputHelper output)
        {
            outputHelper = output;
        }

        private ConsulDispatch BuildConsul()
        {
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddLogging();
            serviceCollection.AddOdysseyHttp((httpConfiguration) =>
            {
                httpConfiguration.JsonSerializerSettingsBuilder = () =>
                {
                    return new JsonSerializerSettings()
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                        DefaultValueHandling = DefaultValueHandling.Ignore,
                    };
                };
                httpConfiguration.HttpResponseFilter = async (httpResponseMessage) =>
                {
                    if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
                    {
                        var errorContent = await httpResponseMessage.Content.ReadAsStringAsync();
                        outputHelper.WriteLine(errorContent);
                        httpResponseMessage.EnsureSuccessStatusCode();
                    }
                };
            }).AddConsulCore((consulConfiguration) =>
            {

                consulConfiguration.Host = "http://localhost:8500";
                consulConfiguration.AccessorID = "9d4786d8-a073-0778-b45d-d4fc3197b19c";
                consulConfiguration.SecretID = "d163859b-8363-4e37-7acf-913be2fd66b5";

                //consulConfiguration.AccessorID = "9d4786d8-a073-0778-b45d-d4fc3197b19c";
                //consulConfiguration.SecretID = "2e08b156-f3f3-c072-adab-896833d44625";
            });

            return serviceCollection.BuildServiceProvider().GetRequiredService<ConsulDispatch>();
        }

        [Fact]
        public void BootstrapTest()
        {
            var consul = BuildConsul();
            var result = consul.ACLs.Bootstrap().Result;
        }

        [Fact]
        public void ReplicationTest()
        {
            var consul = BuildConsul();
            var result = consul.ACLs.Replication().Result;
            Assert.True(result != null);
        }

        [Fact]
        public void LoginTest()
        {
            var consul = BuildConsul();
            var result = consul.ACLs.Login(new ArguLogin()
            {
                AuthMethod = "minikube",
                BearerToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9...",
            }).Result;
        }

        [Fact]
        public void PolicyTest()
        {
            var name = "consul-server-one";
            var consul = BuildConsul();

            var policies = consul.ACLs.PolicyList().Result;

            foreach (var item in policies)
            {
                if (name.Equals(item.Name))
                {
                    outputHelper.WriteLine($"delete {item.Name} policies...");
                    consul.ACLs.PolicyDelete(item.ID).Wait();
                }
            }
            var policyCreate = consul.ACLs.PolicyCreate(new ArguPolicy()
            {
                Name = name,
                Description = "consul-server-one policy test",
                Rules = ACLRule.NodeBuild("consul-server-one", EnumPolicyControlLevel.Write)
            }).Result;

            var policyRead = consul.ACLs.PolicyRead(policyCreate.ID).Result;
            var policyUpdate = consul.ACLs.PolicyUpdate(new ArguPolicy()
            {
                ID = policyRead.ID,
                Datacenters = policyRead.Datacenters,
                Description = policyRead.Description,
                Name = policyRead.Name,
                Rules = policyRead.Rules
            }).Result;

            //consul.ACLs.PolicyDelete(policyUpdate.ID).Wait();
        }

        [Fact]
        public void TokenTest()
        {
            var consul = BuildConsul();

            var tokens = consul.ACLs.TokenList().Result;
            outputHelper.WriteLine("token list info:");
            foreach (var item in tokens)
            {
                outputHelper.WriteLine(JsonConvert.SerializeObject(item));
                if (item.Description.StartsWith("consul-server-one agent token"))
                {
                    consul.ACLs.TokenDelete(item.AccessorID).Wait();
                    outputHelper.WriteLine($"delete {item.AccessorID} success");
                }
                outputHelper.WriteLine("");
            }

            var token = consul.ACLs.TokenCreate(new ArguToken()
            {
                Description = "consul-server-one agent token",
                Policies = new List<PolicyLink>() {
                        new PolicyLink(){
                             Name="consul-server-one"
                        }
                    },
                //Local = false,
                //ExpirationTime = DateTime.Now.AddDays(30)
            }).Result;

            outputHelper.WriteLine("create token:");
            outputHelper.WriteLine(JsonConvert.SerializeObject(token));

            var tokenRead = consul.ACLs.TokenRead(token.AccessorID).Result;
            Assert.Equal(token.SecretID, tokenRead.SecretID);



            var tokenClone = consul.ACLs.TokenClone(new ArguToken()
            {
                AccessorID = token.AccessorID,
                Description = "consul-server-one agent token 2",
            }).Result;
            Assert.Equal(token.Policies[0].Name, tokenClone.Policies[0].Name);
            Assert.NotEqual(token.AccessorID, tokenClone.AccessorID);
            Assert.NotEqual(token.SecretID, tokenClone.SecretID);
            Assert.True(tokenClone.Description.Equals("consul-server-one agent token 2") == true);

            tokenClone = consul.ACLs.TokenUpdate(new ArguToken()
            {
                AccessorID = tokenClone.AccessorID,
                Description = "consul-server-one agent token",
            }).Result;

            var tokenCloneReadSelf = consul.ACLs.TokenReadSelf(tokenClone.SecretID).Result;
            Assert.True(tokenClone.Description == "consul-server-one agent token");
            Assert.Equal(tokenClone.SecretID, tokenCloneReadSelf.SecretID);
            Assert.Equal(tokenClone.AccessorID, tokenCloneReadSelf.AccessorID);
        }

       


    }
}
